<?php 

/**
 * @category Noginn
 * @package Noginn_Geocoder
 */
class Noginn_Geocoder_LocationList implements SeekableIterator, Countable
{
    /**
     * The locations
     *
     * @var array
     */
    protected $_locations;
    
    /**
     * The current countable index
     *
     * @var int
     */
    protected $_currentIndex = 0;
    
    /**
     * Constructor.
     *
     * @param array $locations 
     * @return void
     */
    public function __construct($locations = null)
    {
        if (is_array($locations)) {
            $this->_locations = $locations;
        }
    }
    
    /**
     * Returns the locations
     *
     * @return array
     */
    public function getLocations()
    {
        return $this->_locations;
    }
    
    /**
     * Add a result to the result set
     *
     * @param Noginn_Geocoder_Location $location 
     */
    public function addLocation(Noginn_Geocoder_Location $location)
    {
        $this->_locations[] = $location;
    }
    
    /**
     * Get the geocode result with the highest accuracy
     *
     * @return Noginn_Geocoder_Location
     */
    public function getMostAcurate()
    {
        $mostAcurate = false;
        foreach ($this->_locations as $location) {
            if (!$mostAcurate || $mostAcurate->accuracy < $location->accuracy) {
                $mostAcurate = $location;
            }
        }
        
        return $mostAcurate;
    }
    
    /**
     * Return number of results
     *
     * Implement Countable::count()
     *
     * @return int
     */
    public function count()
    {
        return count($this->_locations);
    }
    
    /**
     * Implements SeekableIterator::current()
     *
     * @return Noginn_Geocoder_Location
     */
    public function current()
    {
        return $this->_locations[$this->_currentIndex];
    }
    
    /**
     * Implements SeekableIterator::key()
     *
     * @return int
     */
    public function key()
    {
        return $this->_currentIndex;
    }

    /**
     * Implements SeekableIterator::next()
     *
     * @return void
     */
    public function next()
    {
        $this->_currentIndex += 1;
    }

    /**
     * Implements SeekableIterator::rewind()
     *
     * @return void
     */
    public function rewind()
    {
        $this->_currentIndex = 0;
    }
    
    /**
     * Implements SeekableIterator::seek()
     *
     * @param  int $index
     * @throws OutOfBoundsException
     * @return void
     */
    public function seek($index)
    {
        $indexInt = (int) $index;
        if ($indexInt >= 0 && $indexInt < $this->_locations->length) {
            $this->_currentIndex = $indexInt;
        }
        else {
            throw new OutOfBoundsException("Illegal index '$index'");
        }
    }
    
    /**
     * Implements SeekableIterator::valid()
     *
     * @return boolean
     */
    public function valid()
    {
        return $this->_currentIndex < count($this->_locations);
    }
}